/**
 * 
 */
package nettoyage;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Vector;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.safety.Whitelist;

import general.Page;
import general.VariablesGlobales;

/**
 * Classe permettant de lancer le nettoyage des pages structurees, cad suppression du code html inutile.<br>
 * Le nettoyage applique ici est extremement basique, on enleve le head et on nettoie le code HTML.<br>
 * Pour un nettoyage qui enleve les parties qui n'ont pas de contenu interessant, on pourrait<br>
 * comparer les arbres DOM de fichiers au sein d'un cluster et supprimer les elements<br>
 * identiques.<br>
 * Pour le choix des blocs a comparer et une methode plus efficace avec des acces a plus de<br>
 * parametres pour appliquer une heuristique, il faudrait utiliser l'algorithme de segmentation<br>
 * VIPS (vision-based page segmentation) que nous n'avons pas eu le temps de mettre en oeuvre.<p>
 * Usage : donner leurs valeurs aux champs statiques VariablesGlobales.fichierSortieClassification<br>
 * (et VariablesGlobales.fichierSortieNettoyage si on ne veut pas ecraser les fichiers)<br>
 * puis lancerNettoyage()<br>
 * Le dossier input doit contenir des dossiers qui correspondent aux clusters, contenant chacun des pages html.
 * @author remi
 * @version 1.0
 */
public class Nettoyage {


	private static String nomDossierInput = null;
	private static String nomDossierOutput = null;
	private static File dossierInput;
	/**
	 * Constructeur vide
	 */
	public Nettoyage() {
	}

	/**
	 * Lancer le nettoyage des pages dans le dossier
	 * @param dossierInputNettoyage dossier d'entree, contenant des dossiers de clusters
	 * @param dossierOutputNettoyage dossier de sortie. Si "" ou null, on prend le meme dossier qu'en entree 
	 */
	public static void lancerNettoyage() {
		
		Nettoyage.setInput(VariablesGlobales.fichierSortieClassification);//recupere le repertoire de classification
		Nettoyage.setOutput(VariablesGlobales.fichierSortieNettoyage);//recupere le repertoire de sortie de la partie nettoyage
		
		if (nomDossierInput == null || nomDossierInput.equals("")) {
			System.err.println("Pas de dossier d'entree specifie pour le nettoyage ! On ne peut pas lancer le nettoyage.");
			return;
		}

		if (nomDossierOutput == null || nomDossierOutput.equals("") ) {
			nomDossierOutput = nomDossierInput;
			System.out.println("Pas de dossier de sortie specifie pour le nettoyage, on reecrit dans le dossier d'entree");
		}

		Vector<Vector<Page>> lesClusters = new Vector<Vector<Page>>();

		if ( dossierInput.isDirectory() && dossierInput.isHidden()==false) {
			File[] list = dossierInput.listFiles();
			Vector<Page> unCluster;
			if (list != null){
				for ( int i = 0; i < list.length; i++) {
					unCluster = new Vector<Page>();
					lesClusters.add(unCluster);
					io.ImporterFichierHTML.creerPagesAPartirDunRepertoire( list[i], unCluster);
				}
			}
			else {
				System.err.println(dossierInput + " : Erreur de lecture (dossier vide?)");
			}
		}
		else{System.err.println(dossierInput + " : Pas un dossier non-hidden");
		}

		//boucle sur tous les clusters/dossiers contenus dans le dossier en entree
		for (Vector<Page> unCluster : lesClusters ) {
			Vector<Document> documentsCluser = new Vector<Document>();
			//boucle sur les pages d'un cluster
			for (Page page : unCluster ) {
				Document document;
				try {//on parse le fichier html correspondant à la page
					document = Jsoup.parse(page.getFichier(),"UTF-8");
				} catch (IOException e) {
					System.err.println("probleme lors du parsing d'une page html, le chemin du fichier n'est pas le bon");
					document = null;
					e.printStackTrace();
				}
				documentsCluser.add(document);
			}


			//Ecriture du resultat
			//On commence par creer le dossier pour le cluster
			String dossierSortieCluster = null;
			for (Document doc1 : documentsCluser) {
				try {
					if (doc1.baseUri().lastIndexOf('/') != -1) {
						dossierSortieCluster = nomDossierOutput + doc1.baseUri().substring(doc1.baseUri().lastIndexOf('/', doc1.baseUri().lastIndexOf('/') - 1), doc1.baseUri().lastIndexOf('/'));
					}
					else {
						dossierSortieCluster = nomDossierOutput + doc1.baseUri().substring(doc1.baseUri().lastIndexOf('\\', doc1.baseUri().lastIndexOf('\\') - 1), doc1.baseUri().lastIndexOf('\\'));
					}
				}
				catch(java.lang.StringIndexOutOfBoundsException e) {
					System.err.println("Erreur a l'ecriture apres nettoyage : trouve pas de separateur de dossiers dans le nom de fichier.\n"+ e.getMessage());
				}
				try {
					new File(dossierSortieCluster).mkdirs();
				}
				catch (Exception e) {
					System.err.println("Erreur a l'ecriture apres nettoyage lors de la creation du dossier du cluster.\n"+ e.getMessage());
				}
				//on s'arrete a un element, suffit pour creer le dossier du cluster
				break;
			}

			String nomFichier = null;
			File fichierCourant;
			String htmlNettoye;
			//On ecrit chaque page nettoyee du cluster dans le dossier de sortie
			for (Document docCourant : documentsCluser) {

				//NETTOYAGE
				//Le nettoyage applique ici est extremement basique, on enleve le <head>
				//et on nettoie le code HTML.
				//Pour un nettoyage qui enleve les parties qui n'ont pas de contenu interessant, on pourrait
				//comparer les arbres DOM de fichiers au sein d'un cluster et supprimer les elements
				//identiques.
				//Pour le choix des blocs a comparer et une methode plus efficace avec des acces a plus de
				//parametres pour appliquer une heuristique, il faudrait utiliser l'algorithme de segmentation
				//VIPS (vision-based page segmentation)
				htmlNettoye = Jsoup.clean(docCourant.body().html(),Whitelist.relaxed());

				try {
					if (docCourant.baseUri().lastIndexOf('/') != -1) {
						nomFichier = docCourant.baseUri().substring(docCourant.baseUri().lastIndexOf('/'));
					}
					else {
						nomFichier = docCourant.baseUri().substring(docCourant.baseUri().lastIndexOf('\\'));
					}	
				}
				catch(java.lang.StringIndexOutOfBoundsException e) {
					System.err.println("Erreur a l'ecriture apres nettoyage : trouve pas de separateur de dossiers dans le nom de fichier.\n"+ e.getMessage());
				}
				try{
					fichierCourant = new File(dossierSortieCluster + nomFichier);
					if(!fichierCourant.exists()){
						fichierCourant.createNewFile();
					}
					FileWriter fstream = new FileWriter(fichierCourant);
					BufferedWriter out = new BufferedWriter(fstream);
					System.out.println("Ecriture du fichier nettoye : " + fichierCourant);
					out.write(htmlNettoye);
					out.close();
				}
				catch (Exception e){
					System.err.println("Erreur a l'ecriture de fichier apres nettoyage : " + e.getMessage());
				}
			}
		}
	}

	/**
	 * Enregistre le dossier d'entree du nettoyage
	 * @param file Dossier d'entree
	 */
	public static void setInput(File file) {
		dossierInput = file;
		try {
			nomDossierInput = file.getCanonicalPath();
		} catch (IOException e) {
			System.err.println("Erreur pour rentrer le nom du dossier d'entree du nettoyage");
			e.printStackTrace();
		}
		System.out.println();
	}

	/**
	 * Enregistre le dossier de sortie du nettoyage
	 * @param file Dossier de sortie
	 */
	public static void setOutput(File file) {
		try {
			nomDossierOutput = file.getCanonicalPath();
		} catch (IOException e) {
			System.err.println("Erreur pour rentrer le nom du dossier de sortie du nettoyage");
			e.printStackTrace();
		}
		
	}

}
